/**
 * @file   GenericPacket.cpp
 * @author Djuro Drljaca (djurodrljaca@gmail.com)
 * @date   2014-04-21
 * @brief  DON generic packet object (payload data is in a raw form)
 *
 * Copyright 2014  Djuro Drljaca (djurodrljaca@gmail.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <DON/Core/Packet/GenericPacket.h>
#include <DON/Core/Packet/PacketDefines.h>
#include <DON/Core/DataType/Structure.h>
#include <DON/Core/DataType/UInt8.h>
#include <QtCore/QByteArray>

using namespace DON::Core::Packet;
using namespace DON::Core::DataType;

class GenericPacket::Private
{
public:
    Private()
        : payloadData(QByteArray())
    { }

    QByteArray payloadData;
};

GenericPacket::GenericPacket()
    : AbstractPacket(),
      d(new Private())
{
}

GenericPacket::GenericPacket(const quint16 source,
                             const quint16 destination,
                             const PacketType packetType,
                             const quint16 sequence)
    : AbstractPacket(source,
                     destination,
                     packetType,
                     sequence),
      d(new Private())
{
}

GenericPacket::GenericPacket(const quint16 source,
                             const quint16 destination,
                             const PacketType packetType,
                             const quint16 sequence,
                             const QByteArray &payloadData)
    : AbstractPacket(source,
                     destination,
                     packetType,
                     sequence),
      d(new Private())
{
    d->payloadData = payloadData;
}

GenericPacket::GenericPacket(const GenericPacket &other)
    : AbstractPacket(other),
      d(new Private())
{
    d->payloadData = other.d->payloadData;
}

GenericPacket::~GenericPacket()
{
    delete d;
}

GenericPacket & GenericPacket::operator=(const GenericPacket &other)
{
    AbstractPacket::operator=(other);

    d->payloadData = other.d->payloadData;

    return *this;
}

bool GenericPacket::isValid() const
{
    bool valid = false;

    if (isPacketTypeValid(getPacketType()) &&
        (d->payloadData.size() <= DON_CORE_PACKET_MAX_PAYLOAD_DATA_SIZE))
    {
        valid = true;
    }

    return valid;
}

bool GenericPacket::isGenericPacketInstance() const
{
    return true;
}

QByteArray GenericPacket::getPayloadData() const
{
    return d->payloadData;
}

bool GenericPacket::setPayloadData(const QByteArray &payloadData)
{
    bool success = false;

    if (payloadData.size() <= DON_CORE_PACKET_MAX_PAYLOAD_DATA_SIZE)
    {
        d->payloadData = payloadData;
        success = true;
    }

    return success;
}

const Structure * GenericPacket::getPayloadItems(bool *ok) const
{
    bool success = false;
    Structure *items = NULL;

    if (isValid())
    {
        // Parse item list (it has the same format as a DON structure)
        items = new Structure();
        int size = 0;

        success = items->fromBinary(d->payloadData, 0, &size);

        if (success)
        {
            // Check if all bytes of the payload data were used
            if (size != d->payloadData.size())
            {
                success = false;
            }
        }

        if (success == false)
        {
            // Error
            delete items;
            items = NULL;
        }
    }

    if (ok != NULL)
    {
        *ok = success;
    }

    return items;
}

int GenericPacket::getMaxPayloadDataSize()
{
    return DON_CORE_PACKET_MAX_PAYLOAD_DATA_SIZE;
}

QByteArray GenericPacket::toBinary() const
{
    return AbstractPacket::toBinary(d->payloadData);
}

QList<QByteArray> GenericPacket::getPayloadDataItems(bool *ok) const
{
    if (ok != NULL)
    {
        *ok = false;
    }

    return QList<QByteArray>();
}
